home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / smaltalk.lha / smalltalk-1.1.1 / CompiledMethod.st < prev    next >
Text File  |  1991-09-12  |  17KB  |  588 lines

  1. "======================================================================
  2. |
  3. |   CompiledMethod Method Definitions
  4. |
  5.  ======================================================================"
  6.  
  7.  
  8. "======================================================================
  9. |
  10. | Copyright (C) 1990, 1991 Free Software Foundation, Inc.
  11. | Written by Steve Byrne.
  12. |
  13. | This file is part of GNU Smalltalk.
  14. |
  15. | GNU Smalltalk is free software; you can redistribute it and/or modify it
  16. | under the terms of the GNU General Public License as published by the Free
  17. | Software Foundation; either version 1, or (at your option) any later version.
  18. | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  19. | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. | FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  21. | details.
  22. | You should have received a copy of the GNU General Public License along with
  23. | GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  24. | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  25. |
  26.  ======================================================================"
  27.  
  28.  
  29. "
  30. |     Change Log
  31. | ============================================================================
  32. | Author       Date       Change 
  33. | sbyrne     27 Dec 89      Added real print method for compiled methods.
  34. |
  35. | sbyrne      6 Sep 89      Added lots of methods: inspect, =, hash, method
  36. |              cateogry, methodSourceCode, methodSourceString, and
  37. |              some private accessors such as bytecodeAt:.
  38. |
  39. | sbyrne     25 Apr 89      created.
  40. |
  41. "
  42.  
  43. ArrayedCollection variableByteSubclass: #CompiledMethod
  44.           instanceVariableNames: 'descriptor methodHeader'
  45.           classVariableNames: ''
  46.           poolDictionaries: ''
  47.           category: nil.
  48.  
  49. CompiledMethod comment:
  50. 'I represent methods that have been compiled.  I can recompile
  51. methods from their source code, I can invoke Emacs to edit the source code
  52. for one of my instances, and I know how to access components of my
  53. instances.' !
  54.  
  55.  
  56. "Make sure that this symbol is defined, even if it doesn't work just
  57. yet."
  58. Smalltalk at: #Debugger put: nil!
  59.  
  60. !CompiledMethod methodsFor: 'basic'!
  61.  
  62. methodCategory
  63.     ^descriptor category
  64. !
  65.  
  66. methodCategory: aCategory
  67.     ^descriptor category: aCategory
  68. !
  69.  
  70. methodSourceCode
  71.     ^descriptor sourceCode
  72. !
  73.  
  74. methodSourceString
  75.     ^descriptor sourceString
  76. !
  77.  
  78. methodSourceFile
  79.     ^descriptor sourceFile
  80. !
  81.  
  82. methodSourcePos
  83.     ^descriptor sourcePos
  84. !
  85.  
  86. = aMethod
  87.     descriptor = aMethod getDescriptor ifFalse: [ ^false ].
  88.     methodHeader = aMethod getHeader ifFalse: [ ^false ].
  89.     1 to: self numLiterals do:
  90.         [ :i |  (self literalAt: i) = (aMethod literalAt: i)
  91.                 ifFalse: [ ^false ] ].
  92.     1 to: self numBytecodes do:
  93.         [ :i | (self bytecodeAt: i) = (aMethod bytecodeAt: i)
  94.                 ifFalse: [ ^false ] ].
  95.     ^true
  96. !
  97.  
  98. hash
  99.     | hashValue |
  100.     hashValue _ descriptor hash.
  101.     hashValue _ ((hashValue bitShift: 1)
  102.                   bitXor: methodHeader hash)
  103.           bitAnd: 16r1FFFFFFF.
  104.     1 to: self numLiterals do:
  105.         [ :i | hashValue _ ((hashValue bitShift: 1)
  106.                             bitXor: (self literalAt: i) hash)
  107.                      bitAnd: 16r1FFFFFFF ].
  108.     1 to: self numBytecodes do:
  109.         [ :i | hashValue _ ((hashValue bitShift: 1)
  110.                              bitXor: (self bytecodeAt: i) hash)
  111.                      bitAnd: 16r1FFFFFFF ].
  112.     ^hashValue
  113. !!
  114.  
  115.  
  116.  
  117. !CompiledMethod methodsFor: 'method header accessors'!
  118.  
  119. "The structure of a method header is as follows (from mstinterp.h)
  120.  
  121.    3                   2                   1 
  122.  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  123. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  124. |1|.|.|.|.|.|flg| prim index    | #args   | #temps  | #literals |
  125. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  126.  
  127. literals 6 0..5
  128. temporarycount 5 6..10
  129. args 5 11..15
  130. primitiveIndex 8 16..23
  131. flags 2 24-25
  132. flags 0 -- use arguments as they are, ignore prim index
  133. flags 1 -- return self
  134. flags 2 -- return instance variable
  135. flags 3 -- call the primitive indexed by primIndex
  136. "
  137.  
  138. flags
  139.     ^(methodHeader bitShift: -24) bitAnd: 16r3
  140. !
  141.  
  142. primitive
  143.     ^(methodHeader bitShift: -16) bitAnd: 16rFF
  144. !
  145.  
  146. numArgs
  147.     | flags |
  148.     flags _ self flags.
  149.     (flags = 2) | (flags = 3)
  150.         ifTrue: [ ^0 ].
  151.     ^(methodHeader bitShift: -11) bitAnd: 16r1F
  152. !
  153.  
  154. numTemps
  155.     self flags = 0
  156.         ifFalse: [ ^0 ].
  157.     ^(methodHeader bitShift: -6) bitAnd: 16r1F
  158. !
  159.  
  160. numLiterals
  161.     self flags = 0
  162.         ifFalse: [ ^0 ].
  163.     ^methodHeader bitAnd: 16r3F
  164. !!
  165.  
  166.  
  167.  
  168. !CompiledMethod methodsFor: 'copying'!
  169.  
  170. shallowCopy
  171.     ^(CompiledMethod newMethod: self basicSize
  172.              header: methodHeader) shallowCopyMethodContents: self
  173. !
  174.  
  175. deepCopy
  176.     ^(CompiledMethod newMethod: self basicSize
  177.              header: methodHeader) deepCopyMethodContents: self
  178. !!
  179.  
  180.  
  181.  
  182. !CompiledMethod methodsFor: 'debugging'!
  183.  
  184. inspect
  185.     | class instVars |
  186.     class _ self class.
  187.     instVars _ class instVarNames.
  188.     'An instance of ' print.
  189.     class printNl.
  190.     1 to: (instVars size - 1) do: "assumes methodHeader is last inst var"
  191.         [ :i | '  ' print.
  192.            (instVars at: i) print.
  193.            ': ' print.
  194.            (self objectAt: i)  printNl ].
  195.     '  Header Flags: ' printNl.
  196.     '    flags: ' print.
  197.     self flags printNl.
  198.     '    primitive index: ' print.
  199.     self primitive printNl.
  200.     '    number of arguments: ' print.
  201.     self numArgs printNl.
  202.     '    number of temporaries: ' print.
  203.     self numTemps printNl.
  204.     '    number of literals: ' print.
  205.     self numLiterals printNl.
  206.     self numLiterals > 0
  207.         ifTrue: [ '  literals: [' printNl.
  208.           1 to: self numLiterals do:
  209.               [ :i | '    ' print.
  210.                  i print.
  211.                  ': ' print.
  212.                  (self literalAt: i) storeNl ].
  213.           '  ]' printNl ]
  214. !!
  215.  
  216.  
  217.  
  218. !CompiledMethod methodsFor: 'debugging'!
  219. breakpointAt: byteIndex
  220.     "self notYetImplemented"
  221.     Debugger recordOldByte: (self bytecodeAt: byteIndex)
  222.          atIndex: byteIndex
  223.          forMethod: self.
  224.     self bytecodeAt: byteIndex put: Debugger debugByte
  225. !
  226.  
  227. breakAtLine: lineNumber
  228.     self notYetImplemented
  229. !
  230.  
  231. removeBreakpointAt: byteIndex
  232.     | oldByte |
  233.     oldByte _ Debugger origByteAt: byteIndex forMethod: self.
  234.     oldByte notNil 
  235.     ifTrue: [ self bytecodeAt: byteIndex put: oldByte ]
  236. !!
  237.  
  238.  
  239.  
  240. !CompiledMethod methodsFor: 'printing'!
  241.  
  242. printOn: aStream
  243.     "### This could be more interesting, such as calling the decompiler, or
  244.      printing out the byte codes, or ... yeah, yeah, that's it, the byte
  245.      codes...also need to decode the header information to display that
  246.      interesting information"
  247.     | primIndex numLits |
  248.     true 
  249.     ifTrue: [ 'a CompiledMethod' printOn: aStream. ]
  250.     ifFalse: 
  251.         [ 'Header Info: ' printOn: aStream.
  252.           (primIndex _ self primitive) > 0 
  253.           ifTrue: [ 'Primitive: ' printOn: aStream ].
  254.           numLits _ self numLiterals.
  255.           ' # Args: ' printOn: aStream.
  256.           (self numArgs) printOn: aStream.
  257.           ' # Temps: ' printOn: aStream.
  258.           (self numTemps) printOn: aStream.
  259.           ' # Literals: ' printOn: aStream.
  260.           numLits printOn: aStream. aStream nl.
  261.           numLits > 0 
  262.           ifTrue: [ 'Literals' printOn: aStream. aStream nl.
  263.                 '--------' printOn: aStream. aStream nl.
  264.                 1 to: numLits do:
  265.                 [ :i | '    [' printOn: aStream.
  266.                        i printOn: aStream.
  267.                        ']: ' printOn: aStream.
  268.                        (self literalAt: i) storeOn: aStream.
  269.                        aStream nl ] ].
  270.           " Emit header info here too "
  271.              'Byte codes' printOn: aStream. aStream nl.
  272.           '----------' printOn: aStream. aStream nl.
  273.           self printByteCodesOn: aStream ]
  274.                          
  275. !
  276.  
  277. storeOn: aStream
  278.     self printOn: aStream
  279. !!
  280.  
  281.  
  282.  
  283. !CompiledMethod methodsFor: 'private'!
  284.  
  285. shallowCopyMethodContents: aMethod 
  286.     "Don't need to copy the method header; it's already done"
  287.     descriptor _ aMethod getDescriptor.
  288.     1 to: aMethod numLiterals do:
  289.         [ :i | self literalAt: i put: (aMethod literalAt: i) ].
  290.     1 to: aMethod numBytecodes do:
  291.         [ :i | self bytecodeAt: i put: (aMethod bytecodeAt: i) ]
  292. !
  293.  
  294. deepCopyMethodContents: aMethod
  295.     "Don't need to copy the method header; it's already done"
  296.     descriptor _ aMethod getDescriptor deepCopy.
  297.     1 to: aMethod numLiterals do:
  298.         [ :i | self literalAt: i put: (aMethod literalAt: i) deepCopy ].
  299.     1 to: aMethod numBytecodes do:
  300.         [ :i | self bytecodeAt: i put: (aMethod bytecodeAt: i) ]
  301. !
  302.  
  303. printByteCodesOn: aStream
  304.     | numBytes i |
  305.     i _ 1.
  306.     numBytes _ self numBytecodes.
  307.     [ i <= numBytes ] whileTrue:
  308.     [ i _ i + (self printByteAt: i on: aStream) ]
  309. !
  310.  
  311.  
  312. printByteAt: anIndex on: aStream
  313.     | byte nextByte skip |
  314.     byte _ self bytecodeAt: anIndex.
  315.     byte == 127 "Debugger debugByte"
  316.     ifTrue: [ byte _ Debugger origByteAt: anIndex forMethod: self ].
  317.     skip _ 1.
  318.     '    [' printOn: aStream.
  319.     anIndex printOn: aStream.
  320.     ']: ' printOn: aStream.
  321.     byte < 95 ifTrue:
  322.     [ self printIndexedAt: anIndex on: aStream ].
  323.     (byte between: 96 and: 111) ifTrue:
  324.     [ self emitSimplePop: byte on: aStream ].
  325.     (byte between: 112 and: 125) ifTrue: 
  326.     [ self emitBuiltin: byte on: aStream ].
  327.     "127 is the debugger breakpoint and we don't get it here"
  328.     byte == 128 ifTrue: 
  329.     [ skip _ 2.
  330.       self print2BytePush: (self bytecodeAt: anIndex + 1) on: aStream ].
  331.     byte == 129 ifTrue: 
  332.     [ skip _ 2.
  333.       self print2ByteStackOp: 'store' at: anIndex on: aStream ].
  334.     byte == 130 ifTrue: 
  335.     [ skip _ 2.
  336.       self print2ByteStackOp: 'pop and store' at: anIndex on: aStream ].
  337.     (byte between: 131 and: 134) ifTrue: 
  338.     [ skip _ self emitIndexedSend: anIndex on: aStream ].
  339.     byte == 135 ifTrue:
  340.     [ 'pop stack top ' printOn: aStream ].
  341.     byte == 136 ifTrue:
  342.     [ 'duplicate stack top' printOn: aStream ].
  343.     byte == 137 ifTrue: 
  344.     [ 'push current context' printOn: aStream ].
  345.     (byte between: 138 and: 143) ifTrue:
  346.     [ 'ILLEGAL bytecode ' printOn: aStream.
  347.       byte printOn: aStream ].
  348.     (byte between: 144 and: 175) ifTrue:
  349.     [ skip _ self printJump: anIndex on: aStream ].
  350.     (byte between: 176 and: 191) ifTrue:
  351.     [ 'send arithmetic message "' printOn: aStream.
  352.       (#(+            -           <            >
  353.          <=         >=          =            ~=
  354.          *            /           \\            @
  355.          bitShift:    //          bitAnd:     bitOr:)
  356.            at: (byte bitAnd: 15) + 1) printOn: aStream.
  357.       '"' printOn: aStream ].
  358.     (byte between: 192 and: 207) ifTrue:
  359.     [ 'send special message "' printOn: aStream.
  360.       (#(at:        at:put:        size        next
  361.             nextPut:    atEnd        ==            class
  362.             blockCopy:    value        value:      do:
  363.         new            new:        x            y)
  364.            at: (byte bitAnd: 15) + 1) printOn: aStream.
  365.       '"' printOn: aStream ].
  366.     (byte between: 208 and: 255) ifTrue:
  367.     [ self printSmallArgSend: byte on: aStream ].
  368.     aStream nextPut: (Character nl).
  369.     ^skip
  370. !    
  371.  
  372. printIndexedAt: anIndex on: aStream
  373.     | byte index |
  374.     byte _ self bytecodeAt: anIndex.
  375.     byte <= 15 ifTrue:
  376.         [ ^self pushIndexed: 'Instance Variable' 
  377.         withIndex: (byte bitAnd: 15)
  378.         on: aStream ].
  379.     byte <= 31 ifTrue:
  380.     [ ^self pushIndexed: 'Temporary'
  381.         withIndex: (byte bitAnd: 15)
  382.         on: aStream ].
  383.     byte <= 63 ifTrue:
  384.     [ ^self pushIndexed: 'Literal'
  385.         withIndex: (byte bitAnd: 31)
  386.         on: aStream ].
  387.  
  388.     " >= 64 case here "
  389.     'push Global Variable[' printOn: aStream.
  390.     (byte bitAnd: 31) printOn: aStream.
  391.     '] = ' printOn: aStream.
  392.     self printAssociationKeyFor: (byte bitAnd: 31) on: aStream
  393. !
  394.  
  395. pushIndexed: indexLabel withIndex: anIndex on: aStream
  396.     'push ' printOn: aStream.
  397.     indexLabel printOn: aStream.
  398.     '[' printOn: aStream.
  399.     anIndex printOn: aStream.
  400.     ']' printOn: aStream
  401. !
  402.  
  403. emitSimplePop: byte on: aStream
  404.     (byte between: 96 and: 103) ifTrue:
  405.     [ aStream nextPutAll: 'pop and store instance variable['.
  406.       (byte bitAnd: 7) printOn: aStream.
  407.       aStream nextPut: $] ].
  408.     (byte between: 104 and: 111) ifTrue:
  409.     [ aStream nextPutAll: 'pop and store Temporary['.
  410.       (byte bitAnd: 7) printOn: aStream.
  411.       aStream nextPut: $] ].
  412. !
  413.  
  414. emitBuiltin: byte on: aStream
  415.     byte == 112 ifTrue: [ 'push self' printOn: aStream ].
  416.     byte == 113 ifTrue: [ 'push true' printOn: aStream ].
  417.     byte == 114 ifTrue: [ 'push false' printOn: aStream ].
  418.     byte == 115 ifTrue: [ 'push nil' printOn: aStream ].
  419.     byte == 116 ifTrue: [ 'push -1' printOn: aStream ].
  420.     byte == 117 ifTrue: [ 'push 0' printOn: aStream ].
  421.     byte == 118 ifTrue: [ 'push 1' printOn: aStream ].
  422.     byte == 119 ifTrue: [ 'push 2' printOn: aStream ].
  423.     byte == 120 ifTrue: [ 'return self' printOn: aStream ].
  424.     byte == 121 ifTrue: [ 'return true' printOn: aStream ].
  425.     byte == 122 ifTrue: [ 'return false' printOn: aStream ].
  426.     byte == 123 ifTrue: [ 'return nil' printOn: aStream ].
  427.     byte == 124 ifTrue: [ 'return Message stack top' printOn: aStream ].
  428.     byte == 125 ifTrue: [ 'return Block stack top' printOn: aStream ].
  429.     byte == 126 ifTrue: [ '### ILLEGAL BYTE CODE 126 ###' printOn: aStream ].
  430. !
  431.  
  432. print2BytePush: byte on: aStream
  433.     self printIndexedPush: (byte bitAnd: 63)
  434.      type: (byte bitShift: -6)
  435.      on: aStream
  436. !
  437.  
  438. printIndexedPush: index type: typeIndex on: aStream
  439.     | typeName |
  440.     typeName _ self indexedLocationName: typeIndex.
  441.     'push ' , typeName , '[' printOn: aStream.
  442.     index printOn: aStream.
  443.     ']' printOn: aStream.
  444.     typeIndex = 3 ifTrue:
  445.     [ ' = ' printOn: aStream.
  446.       self printAssociationKeyFor: index
  447.            on: aStream ]
  448. !
  449.  
  450. indexedLocationName: locIndex
  451.     ^#('Instance Variable' 'Temporary' 'Literal' 'Global Variable')
  452.     at: locIndex + 1
  453. !
  454.  
  455. print2ByteStackOp: opName at: anIndex on: aStream
  456.     | nextByte locationName locIndex |
  457.     nextByte _ self bytecodeAt: anIndex + 1.
  458.     locIndex _ nextByte bitShift: -6.
  459.     locationName _ self indexedLocationName: locIndex.
  460.     locIndex == 2 ifTrue: [ 'ILLEGAL ' printOn: aStream ].
  461.     opName , locationName , '[' printOn: aStream.
  462.     (nextByte bitAnd: 63) printOn: aStream.
  463.     ']' printOn: aStream.
  464.     locIndex == 3 ifTrue:
  465.     [ ' = ' printOn: aStream.
  466.       self printAssociationKeyFor: (nextByte bitAnd: 63) on: aStream ]
  467. !
  468.  
  469. emitIndexedSend: anIndex on: aStream
  470.     | byte byte1 byte2 toSuper |
  471.     byte _ self bytecodeAt: anIndex.
  472.     byte _ byte - 131.        "transform to 0..3"
  473.     byte <= 1 ifTrue: [ toSuper _ '' ]
  474.           ifFalse: [ toSuper _ 'to Super ' ].
  475.     (byte == 0) | (byte == 2)
  476.     ifTrue:
  477.         [ byte1 _ self bytecodeAt: anIndex + 1.
  478.           self emitGenericSend: toSuper index: (byte1 bitAnd: 31)
  479.            args: (byte1 bitShift: -5) on: aStream.
  480.           ^2 ]
  481.     ifFalse:
  482.         [ byte1 _ self bytecodeAt: anIndex + 1.
  483.           byte2 _ self bytecodeAt: anIndex + 2.
  484.           self emitGenericSend: toSuper index: byte2
  485.            args: byte1 on: aStream.
  486.           ^3]
  487. !
  488.  
  489.  
  490. emitGenericSend: toSuper index: anIndex args: numArgs on: aStream
  491.     'send ' , toSuper , 'selector ' printOn: aStream.
  492.     anIndex printOn: aStream.
  493.     ', ' printOn: aStream.
  494.     numArgs printOn: aStream.
  495.     ' args = ' printOn: aStream.
  496.     self printLiteralSymbolAt: anIndex on: aStream
  497. !
  498.  
  499. printJump: anIndex on: aStream
  500.     | byte |
  501.     byte _ self bytecodeAt: anIndex.
  502.     byte <= 151 ifTrue:
  503.     [ 'jump to ' printOn: aStream.
  504.       ((byte bitAnd: 7) + anIndex + 1 + 1 ) printOn: aStream.
  505.       ^1 ].
  506.     byte <= 159 ifTrue:
  507.     [ 'jump to ' printOn: aStream.
  508.       ((byte bitAnd: 7) + anIndex + 1 + 1 ) printOn: aStream.
  509.       ' if false' printOn: aStream.
  510.       ^1 ].
  511.     byte <= 167 ifTrue:
  512.     [ 'jump to ' printOn: aStream.
  513.       (((byte bitAnd: 7) - 4) * 256 + (self bytecodeAt: anIndex + 1)
  514.           + anIndex + 2) printOn: aStream.
  515.       ^2 ].
  516.     byte <= 171 ifTrue:
  517.     [ 'pop and jump to ' printOn: aStream.
  518.       ((byte bitAnd: 3) * 256 + (self bytecodeAt: anIndex + 1)
  519.           + anIndex + 2) printOn: aStream.
  520.       ' if true' printOn: aStream.
  521.       ^2 ].
  522.     byte <= 175 ifTrue:
  523.     [ 'pop and jump to ' printOn: aStream.
  524.       ((byte bitAnd: 3) * 256 + (self bytecodeAt: anIndex + 1)
  525.           + anIndex + 2) printOn: aStream.
  526.       ' if false' printOn: aStream.
  527.       ^2 ]
  528. !
  529.  
  530. printSmallArgSend: byte on: aStream
  531.     | numArgs |
  532.     byte _ byte - 208.
  533.     numArgs _ byte // 16.
  534.     'send selector ' printOn: aStream.
  535.     (byte bitAnd: 15) printOn: aStream.
  536.     ', ' printOn: aStream.
  537.     numArgs printOn: aStream.
  538.     numArgs == 1 
  539.     ifTrue: [ ' arg' printOn: aStream ]
  540.     ifFalse: [ ' args' printOn: aStream ].
  541.     ' = ' printOn: aStream.
  542.     self printLiteralSymbolAt: (byte bitAnd: 15) on: aStream
  543. !
  544.  
  545. printAssociationKeyFor: anIndex on: aStream
  546.     | assoc |
  547.     assoc _ self literalAt: anIndex + 1.
  548.     assoc key printOn: aStream
  549. !
  550.  
  551. printLiteralSymbolAt: anIndex on: aStream
  552.     (self literalAt: anIndex + 1) printOn: aStream
  553. !
  554.  
  555. getDescriptor
  556.     ^descriptor
  557. !
  558.  
  559. getHeader
  560.     ^methodHeader
  561. !
  562.  
  563. literalAt: anIndex
  564.     ^self objectAt: (anIndex + 2)
  565. !
  566.  
  567. literalAt: anInteger put: aValue
  568.     self objectAt: anInteger + 2 put: aValue
  569. !
  570.  
  571. numBytecodes
  572.     ^(self basicSize) - (self bytecodeStart)
  573. !
  574.  
  575. bytecodeAt: anIndex
  576.     ^self basicAt: (anIndex + self bytecodeStart)
  577. !
  578.  
  579. bytecodeAt: anIndex put: aValue
  580.     ^self basicAt: (anIndex + self bytecodeStart) put: aValue
  581. !
  582.  
  583. bytecodeStart
  584.     ^4 * self numLiterals
  585. !!
  586.